/**
 * Error types for the application
 */
export enum ErrorType {
  VALIDATION = 'validation',
  PROCESSING = 'processing',
  MEMORY = 'memory',
  SYSTEM = 'system',
  UNKNOWN = 'unknown'
}

/**
 * Application error class
 */
export class AppError extends Error {
  type: ErrorType;
  details?: Record<string, any>;

  constructor(message: string, type: ErrorType = ErrorType.UNKNOWN, details?: Record<string, any>) {
    super(message);
    this.name = 'AppError';
    this.type = type;
    this.details = details;
  }
}

/**
 * Validation error class
 */
export class ValidationError extends AppError {
  constructor(message: string, details?: Record<string, any>) {
    super(message, ErrorType.VALIDATION, details);
    this.name = 'ValidationError';
  }
}

/**
 * Processing error class
 */
export class ProcessingError extends AppError {
  constructor(message: string, details?: Record<string, any>) {
    super(message, ErrorType.PROCESSING, details);
    this.name = 'ProcessingError';
  }
}

/**
 * Memory error class
 */
export class MemoryError extends AppError {
  constructor(message: string, details?: Record<string, any>) {
    super(message, ErrorType.MEMORY, details);
    this.name = 'MemoryError';
  }
}

/**
 * System error class
 */
export class SystemError extends AppError {
  constructor(message: string, details?: Record<string, any>) {
    super(message, ErrorType.SYSTEM, details);
    this.name = 'SystemError';
  }
}

/**
 * Handle error and return user-friendly message
 * @param error Error to handle
 * @returns User-friendly error message
 */
export function handleError(error: unknown): string {
  // Log error for debugging
  console.error('Error occurred:', error);
  
  // Handle AppError
  if (error instanceof AppError) {
    return error.message;
  }
  
  // Handle standard Error
  if (error instanceof Error) {
    return error.message;
  }
  
  // Handle unknown error
  return '发生未知错误，请重试';
}

/**
 * Check if browser has enough memory for operation
 * @param requiredBytes Estimated bytes required
 * @returns True if enough memory is available
 */
export function checkMemoryAvailability(requiredBytes: number): boolean {
  // Check if performance.memory is available (Chrome only)
  if ('performance' in window && 'memory' in performance) {
    const memory = (performance as any).memory;
    if (memory && memory.jsHeapSizeLimit) {
      // Leave 20% buffer for other operations
      const availableMemory = memory.jsHeapSizeLimit * 0.8;
      return requiredBytes < availableMemory;
    }
  }
  
  // If we can't check memory, assume it's enough
  // but warn if the required memory is very large
  if (requiredBytes > 500 * 1024 * 1024) { // 500MB
    console.warn('Operation requires significant memory:', requiredBytes / (1024 * 1024), 'MB');
  }
  
  return true;
}

/**
 * Estimate memory required for canvas operation
 * @param width Canvas width
 * @param height Canvas height
 * @returns Estimated bytes required
 */
export function estimateCanvasMemory(width: number, height: number): number {
  // Each pixel uses 4 bytes (RGBA)
  // Add 50% overhead for canvas operations
  return width * height * 4 * 1.5;
}